#include "progresslistener.h"
#include <QDebug>
#include <QThread>
#include <QMutexLocker>
#include <math.h>

void ProgressListener::Info::compute(qint64 bytesProcessed, qint64 totalBytes, qint64 timeElapsed, ShortInfo* predInfo)
{
    this->bytesProcessed = bytesProcessed;
    this->timeElapsed = timeElapsed;
    this->progressVal = round((100.0 * bytesProcessed) / totalBytes);
    this->curSpeed = ((double) (bytesProcessed - predInfo->bytesProcessed)) / (timeElapsed - predInfo->timeElapsed);
    this->avgSpeed = ((double) bytesProcessed) / timeElapsed;
    this->bytesRemaining = totalBytes - bytesProcessed;
    this->timeRemaining = this->bytesRemaining / this->avgSpeed;
}

ProgressListener::ProgressListener(IFileBuffer *fb, int msecInt) :
    fb(fb),
    timer(new QTimer(this))
{
//    qDebug() << "ProgressListener::ProgressListener(IFileBuffer *fb)";

    timer->setInterval(msecInt);
    worker.setMaxThreadCount(1);
    setAutoDelete(false);

    connect(fb, SIGNAL(beginFileLoading(qint64)), SLOT(onBeginOp(qint64)));
    connect(fb, SIGNAL(fileLoaded(QString,qint64)), SLOT(onEndOp()));
    connect(fb, SIGNAL(fileLoadingError(QString,QString,IFileBuffer::State)), SLOT(onEndOp()));

    connect(fb, SIGNAL(beginFileSaving(qint64)), SLOT(onBeginOp(qint64)));
    connect(fb, SIGNAL(fileSaved(QString)), SLOT(onEndOp()));
    connect(fb, SIGNAL(fileSavingError(QString,QString)), SLOT(onEndOp()));

    connect(timer, SIGNAL(timeout()), this, SLOT(scheduleWork()));
}

ProgressListener::~ProgressListener()
{
    timer->stop();
    delete timer;
}

void ProgressListener::onBeginOp(qint64 fileSize)
{
//    qDebug() << "void ProgressListener::onBeginOp(qint64 fileSize)";
//    qDebug() << "fileSize:" << fileSize;
//    qDebug() << "thread:" << thread()->currentThreadId();
    elapsedTimer.start();
    this->fileSize = fileSize;
    predInfo = Info();
//    enableWork();
    timer->start();
}

void ProgressListener::onEndOp()
{
//    qDebug() << "void ProgressListener::onEndOp()";
//    qDebug() << "thread:" << thread()->currentThreadId();
    timer->stop();    
//    disableWork();
}

void ProgressListener::scheduleWork()
{
//    qDebug() << "void ProgressListener::scheduleWork()";
//    qDebug() << "thread:" << thread()->currentThreadId();
    worker.start(this);
}

//void ProgressListener::enableWork()
//{
//    QMutexLocker locker(&workGuard);
//    workEnabled = true;
//}

//void ProgressListener::disableWork()
//{
//    worker.waitForDone();
//    QMutexLocker locker(&workGuard);
//    workEnabled = false;
//}

void ProgressListener::run()
{
//    qDebug() << "void ProgressListener::run()";
//    qDebug() << "thread:" << thread()->currentThreadId();
//    qDebug() << fixed << qSetRealNumberPrecision(1);
//    qDebug() << "progress:" << (100.0 * fb->getBytesProcessed() / fileSize) << "%";
//    QMutexLocker lock(&workGuard);
//    if(workEnabled){
        Info info;
        info.compute(fb->getBytesProcessed(), fileSize, elapsedTimer.elapsed(), &predInfo);
        predInfo = info;
        emit updateInfo(info);
//    }
}
